package com.baidu.ota.application;

import android.app.Activity;
import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.text.TextUtils;
import android.util.Log;

import com.baidu.commonlib.interfaces.ICheckUpdateListener;
import com.baidu.commonlib.interfaces.IOtaAgent;
import com.baidu.commonlib.interfaces.IOtaSdkHelper;
import com.baidu.commonlib.interfaces.IUpgradeInterface;
import com.baidu.ota.interfaces.IActivityProxy;
import com.baidu.ota.interfaces.IApplicationProxy;
import com.baidu.ota.interfaces.IBindListener;
import com.baidu.ota.interfaces.INotifyHandler;
import com.baidu.ota.interfaces.ISystemInfo;
import com.baidu.ota.meta.Config;
import com.baidu.ota.meta.Strings;
import com.baidu.ota.utils.MetaData;
import com.baidu.ota.utils.ProcessUtil;
import com.baidu.ota.utils.StringUtil;
import com.baidu.otasdk.ota.Constants;
import com.baidu.otasdk.ota.OtaApplicationInit;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 抽象Application类
 */
public abstract class BaseApplication extends Application {
    public static boolean waitReboot = false;
    public static boolean nextRebootUpgrade = false;

    private final List<IOtaAgent> otaAgentList = new CopyOnWriteArrayList<>();
    private final List<IBindListener> listeners = new CopyOnWriteArrayList<>();
    private static BaseApplication inst;

    public static BaseApplication getInst() {
        return inst;
    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);

        inst = this;
        MetaData.init(this);
        OtaApplicationInit.attachBaseContext(base, new MyOtaListener());
    }

    @Override
    public void onCreate() {
        super.onCreate();
        OtaApplicationInit.onCreate();

        String name = ProcessUtil.getProcessName(this);
        // 仅主进程注册广播
        if (!name.contains(":")) {
            initBroadcast();
        }
    }

    public abstract IApplicationProxy getApplicationProxy();

    public abstract IActivityProxy getActivityProxy(Activity activity);

    public IOtaAgent getOtaAgent(String pid) {
        for (IOtaAgent otaAgent : otaAgentList) {
            if (otaAgent.getProductId().compareTo(pid) == 0) {
                return otaAgent;
            }
        }
        return null;
    }

    public void registerListener(IBindListener listener) {
        if (listener != null) {

            // 后台启动进程，而Activity没有启动，当Activity主动打开注册时，回调一次
            if (!otaAgentList.isEmpty()) {
                Log.d(Constants.TAG, "listener launch");
                listener.onBind(otaAgentList);
            }
            listeners.add(listener);
        }
    }

    public void unRegisterListener(IBindListener listener) {
        if (listener != null) {
            listeners.remove(listener);
        }
    }

    private void initBroadcast() {
        IntentFilter intentFilter = new IntentFilter(Constants.BROADCAST_NEWVERSION);
        INotifyHandler handler = getApplicationProxy().getNotifyHandler();
        BroadcastReceiver broadcastReceiver = new MyBroadcastReceiver(handler);
        registerReceiver(broadcastReceiver, intentFilter);

        IntentFilter intentFilter2 = new IntentFilter(Constants.BROADCAST_UPGRADE);
        registerReceiver(broadcastReceiver, intentFilter2);

        IntentFilter intentFilter3 = new IntentFilter(Strings.USER_CHECK_UPDATE_BROADCAST);
        registerReceiver(broadcastReceiver, intentFilter3);
    }

    private static class MyBroadcastReceiver extends BroadcastReceiver {
        private static long lastTime = 0;
        private static final long TIME_INTERVAL = 15000;
        private final INotifyHandler handler;

        MyBroadcastReceiver(INotifyHandler h) {
            handler = h;
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action == null || handler == null) {
                return;
            }
            if (action.equals(Constants.BROADCAST_NEWVERSION)) { // SDK自动检查到新版本的通知
                String infoList = intent.getStringExtra(Constants.BROADCAST_KEY_INFOS);
                String pid = intent.getStringExtra(Constants.BROADCAST_KEY_PID);
                String text = String.format(Locale.ROOT, "%s[%s]", infoList, pid);
                Log.i(Constants.TAG, "User App Receive New Version:" + text);
                handler.onNewVersionNotify(pid, infoList);
            } else if (action.equals(Constants.BROADCAST_UPGRADE)) { // 一次升级完成的通知
                String data = intent.getStringExtra(Constants.BROADCAST_UPGRADE_DATA);
                Log.i(Constants.TAG, "User App Receive Upgrade Result:" + data);
                handler.onUpgradedNotify(data);
            } else if (action.equals(Strings.USER_CHECK_UPDATE_BROADCAST)) {
                if (lastTime == 0 || System.currentTimeMillis() - lastTime >= TIME_INTERVAL) {
                    lastTime = System.currentTimeMillis();
                    checkUpdate();
                } else {
                    Log.w(Constants.TAG, "call frequency");
                }
            }
        }
    }

    private static void checkUpdate() {
        for (final IOtaAgent agent : getInst().otaAgentList) {
            final String pid = agent.getProductId();
            Log.i(Constants.TAG, "manualCheck:" + pid);
            agent.checkUpdate(true, new ICheckUpdateListener() {
                @Override
                public void onSuccess(String s) {
                    Log.i(Constants.TAG, "manualCheck success");
                    sendBroadcast(pid, s);
                }

                @Override
                public void onFail(int i, String s) {
                    Log.w(Constants.TAG, "manualCheck fail:" + s);
                }
            });
        }
    }

    private static void sendBroadcast(String pid, String jsonList) {
        Intent intent = new Intent(Constants.BROADCAST_NEWVERSION);
        intent.setPackage(BaseApplication.getInst().getPackageName());
        intent.putExtra(Constants.BROADCAST_KEY_PID, pid);
        intent.putExtra(Constants.BROADCAST_KEY_INFOS, jsonList);

        BaseApplication.getInst().sendBroadcast(intent);
    }

    private class MyOtaListener implements OtaApplicationInit.IOtaListener {

        @Override
        public void initService(IOtaSdkHelper helper) {
            if (helper == null) {
                Log.e(Constants.TAG, "sdk init fail.");
                return;
            }

            IApplicationProxy app = getApplicationProxy();
            ISystemInfo sysInfo = app.getSystemInfo();

            // SDK初始化
            helper.init(sysInfo.getDeviceId(), sysInfo);

            // 设置升级路径
            String path = app.getUpgradePath(getInst());
            if (!TextUtils.isEmpty(path)) {
                helper.setUpgradePath(path);
            }

            // 设置下载选项
            String downloadOpts = MetaData.getString(MetaData.OPTION);
            List<Config.Pair<Integer, String>> opts = StringUtil.parse2IntegerList(downloadOpts);
            for (Config.Pair<Integer, String> opt : opts) {
                helper.setExtOption(opt.key, opt.val);
            }

            // 其他选项
            String extraOpts = MetaData.getString(MetaData.EXTRA);
            opts = StringUtil.parse2IntegerList(extraOpts);
            for (Config.Pair<Integer, String> opt : opts) {
                helper.setExtOption(opt.key, opt.val);
            }

            // 预加载app列表
            List<String> appList = StringUtil.parse2List(MetaData.getString(MetaData.PRESET_APPS));
            if (appList != null && appList.size() > 0) {
                helper.presetAppNames(appList);
            }

            // 获取产品线信息配置
            List<Config.Pair<String, String>> productList = new ArrayList<>();
            String productId = "" + MetaData.getInt(MetaData.PRODUCT_ID);
            String productKey = MetaData.getString(MetaData.PRODUCT_KEY);
            if (!TextUtils.isEmpty(productId) && !TextUtils.isEmpty(productKey)) {
                Config.Pair<String, String> pair = new Config.Pair<>();
                pair.key = productId;
                pair.val = productKey;
                productList.add(pair);
            }
            if (productList.size() == 0) {
                String pid = sysInfo.getFieldValue(0);
                String ps = sysInfo.getFieldValue(1);
                if (!TextUtils.isEmpty(pid) && !TextUtils.isEmpty(ps)) {
                    Config.Pair<String, String> pair = new Config.Pair<>();
                    pair.key = pid;
                    pair.val = ps;
                    productList.add(pair);
                }
            }

            // 初始化产品线
            otaAgentList.clear();
            for (Config.Pair<String, String> p : productList) {
                Log.d(Constants.TAG, "init pid:" + p.key);

                // 获取产品线的ota实例对象
                IOtaAgent otaAgent = helper.getInst(p.key, p.val);
                if (otaAgent == null) {
                    Log.e(Constants.TAG, "getInst fail by " + p.key + "/" + p.val);
                    continue;
                }

                // 添加渠道号
                addChannel(otaAgent, sysInfo);

                // 设置自定义升级对象
                IUpgradeInterface inst = app.getCustomUpgrade(getApplicationContext(), p.key);
                if (inst != null) {
                    otaAgent.setCustomUpgrade(inst);
                }
                otaAgentList.add(otaAgent);
            }
            Log.i(Constants.TAG, "product size=" + productList.size());

            // 允许外部创建
            app.onCreated(helper);

            // 通知ota实例完成创建，可使用了
            if (otaAgentList.size() > 0) {
                for (IBindListener listener : listeners) {
                    listener.onBind(otaAgentList);
                }
            }
        }
    }

    private void addChannel(IOtaAgent otaAgent, ISystemInfo sysInfo) {
        String ch = sysInfo.getChannel();
        if (!TextUtils.isEmpty(ch)) {
            otaAgent.addReqMetaField(Constants.CHANNEL, ch);
        }
    }
}
